package cn.gov.mwr.sl651;

import org.apache.commons.lang3.StringUtils;

import cn.gov.mwr.sl651.header.AscHeader;
import cn.gov.mwr.sl651.utils.ByteUtil;

/**
 * 水文协议构建工具，通过此类可以构建查询消息体
 *
 * @author admin
 */
public class HydroBuilder {

    /**
     * 表58　遥测站状态和报警信息
     *
     * @param bytes
     * @return
     */
    public static int[] buildStatus(byte[] bytes) {
        // 1 交流电充电状态 BIT0 0：正常；1：停电
        // 2 蓄电池电压状态 BIT1 0：正常；1：电压低
        // 3 水位超限报警状态 BIT2 0：正常；1：报警
        // 4 流量超限报警状态 BIT3 0：正常；1：报警
        // 5 水质超限报警状态 BIT4 0：正常；1：报警
        // 6 流量仪表状态 BIT5 0：正常；1：故障
        // 7 水位仪表状态 BIT6 0：正常；1：故障
        // 8 终端箱门状态 BIT7 0：开启；1：关闭
        // 9 存储器状态 BIT8 0：正常；1：异常
        // 10 IC卡功能有效 BIT9 0：关闭；1：IC卡有效
        // 11 水泵工作状态 BIT10 0：水泵工作；1：水泵停机
        // 12 剩余水量报警 BIT11 0：未超限；1：水量超限
        // 13 保留 BIT12～31

        String status = ByteUtil.toBinaryString(bytes);
        int[] intstatus = new int[status.length()];
        for (int i = 0, len = status.length(); i < len; i++) {
            String flag = status.substring(i, i + 1);
            intstatus[i] = Integer.parseInt(flag);
        }

        return intstatus;
    }

    public static String buildDot(String valuestr, int decimal) {
        if (StringUtils.isNotBlank(valuestr)) {
            try {
                int valueint = Integer.parseInt(valuestr.trim());
                String value = Integer.toString(valueint);
                int len = value.length();
                if (decimal == 0)
                    return valuestr;
                if (len > decimal) {
                    String right = value.substring(len - decimal);
                    int pos = StringUtils.lastIndexOf(value, right);
                    String left = value.substring(0, pos);
                    return left + "." + right;
                } else {
                    value = StringUtils.leftPad(value, decimal, "0");
                    value = "0." + value;
                    return value;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    public static int buildDecimal(String value) {
        int end = 0;
        int pos = value.indexOf(".");
        if (pos != -1) {
            String endstr = value.substring(pos + 1);
            end = endstr.length();
        }

        return end;
    }

    /**
     * 合成数据标识符“低位字节”的数据位字节
     *
     * @param value
     */
    public static byte buildDataLength(int len, int decimal) {
        // 开始合并,数据位的位数
        byte hignByte = ByteUtil.ubyteToBytes(len)[0];
        byte lowByte = ByteUtil.ubyteToBytes(decimal)[0];

        byte high = (byte) ((hignByte << 3) & 0xF8);
        byte low = (byte) (lowByte & 0x07);

        return (byte) (high | low);
    }

    /**
     * 起始位
     */
    public static void newStartBit(IMessageHeader header) {
        byte[] startBit = new byte[header.getStartBitLen()];
        if (startBit.length == 1) {
            startBit[0] = Symbol.SOH_ASC;
        } else {
            startBit[0] = Symbol.SOH_HEX;
            startBit[1] = Symbol.SOH_HEX;
        }
        header.setStartBit(startBit);
    }

    /**
     * 中心站地址
     * <p>
     * 取值范围为1-255，对于ASCII模式，需要将1字节的HEX编码转换为两个字符进行传输
     * <p>
     * 因为取值范围为1-255，默认相当于为16进制的数。
     */
    public static void newCenterAddr(IMessageHeader header, String value) {
        byte[] centerAddr = new byte[header.getCenterAddrLen()];

        // HEX编码，value相当于16进制的数
        if (header.getStartBitLen() == 2) {
            centerAddr = ByteUtil.ubyteToBytes(Integer.parseInt(value));
        } else {
            // 需将其转换为字符FF
            String temp = Integer.toHexString(Integer.parseInt(value));
            centerAddr = temp.getBytes();
        }

        header.setCenterAddr(centerAddr);
    }

    public static void newCenterAddr(IMessageHeader header, byte[] value) {
        // HEX编码，value相当于16进制的数
        header.setCenterAddr(value);
        // if (header.getStartBitLen() == 2) {
        // header.setCenterAddr(value);
        // }else{
        // String centerAddr = ByteUtil.toHexString(value);
        // header.setCenterAddr(centerAddr.getBytes());
        // }
    }

    /**
     * 遥测站地址
     * <p>
     * ???????????????还有问题
     */
    public static void newStationAddr(IMessageHeader header, String value) {
        byte[] stationAddr = new byte[header.getStationAddrLen()];

        if (value.length() < 10) {// 表示高字节没有00，需补齐位数
            // int len = 10 - value.length();
            // for (int i = 0; i < len; i++) {
            // value = "0" + value;
            // }
            value = StringUtils.leftPad(value, 10, "0");
        }

        // 判断高字节位是否为00，如果是则为遥测站编码，如果不是则为其他站编码
        String A5 = value.substring(0, 2);
        String A4 = value.substring(2, 4);
        String A3 = value.substring(4, 6);
        String A2 = value.substring(6, 8);
        String A1 = value.substring(8, 10);

        if (A5.equals("00")) {
            stationAddr[0] = 0x00;
            stationAddr[1] = ByteUtil.ubyteToBytes(Integer.parseInt(A4, 16))[0];
            stationAddr[2] = ByteUtil.ubyteToBytes(Integer.parseInt(A3, 16))[0];
            stationAddr[3] = ByteUtil.ubyteToBytes(Integer.parseInt(A2, 16))[0];
            stationAddr[4] = ByteUtil.ubyteToBytes(Integer.parseInt(A1, 16))[0];
        } else {
            // 构建其他站编码
            // 在这块还有问题呢，如果是其他遥测站的地址，在传输的时候，测站码相当于已经转换为16进制的字符
            String A2A1 = value.substring(6, 10);
            byte[] a2a1 = ByteUtil.ushortToBytes(Integer.parseInt(A2A1, 16));
            stationAddr[3] = a2a1[0];
            stationAddr[4] = a2a1[1];
        }

        // HEX编码，value相当于16进制的数
        if (header.getStartBitLen() == 2) {
            header.setStationAddr(stationAddr);
        } else {
            String station = ByteUtil.toHexString(stationAddr);
            header.setStationAddr(station.getBytes());
        }

    }

    public static void newStationAddr(IMessageHeader header, byte[] stationAddr) {
        header.setStationAddr(stationAddr);

        // int len = header.getStationAddrLen();
        // if (len == 5) {
        // header.setStationAddr(stationAddr);
        // } else {
        // String station = ByteUtil.toHexString(stationAddr);
        // header.setStationAddr(station.getBytes());
        // }

    }

    /**
     * 密码
     */
    public static void newPassword(IMessageHeader header, String value) {
        byte[] pwd = new byte[header.getPasswordLen()];

        // HEX编码，value相当于16进制的数
        if (header.getStartBitLen() == 2) {
            int valueint = Integer.parseInt(value, 16);
            pwd = ByteUtil.ushortToBytes(valueint);
        } else {
            // int valueint = Integer.parseInt(value, 16);
            if (value.length() < 4) {
                value = StringUtils.leftPad(value, 4, "0");
            }
            pwd = value.getBytes();
        }

        header.setPassword(pwd);
    }

    public static void newPassword(IMessageHeader header, byte[] pwd) {
        header.setPassword(pwd);
        // if (header.getStartBitLen() == 2) {
        // header.setPassword(pwd);
        // }else{
        // String password = ByteUtil.toHexString(pwd);
        // header.setPassword(password.getBytes());
        // }
    }

    /**
     * 功能码
     */
    public static void newFuncCode(IMessageHeader header, String value) {
        byte[] funcCode = new byte[header.getFuncCodeLen()];

        // HEX编码，value相当于16进制的数
        if (header.getStartBitLen() == 2) {
            int valueint = Integer.parseInt(value, 16);
            funcCode = ByteUtil.ubyteToBytes(valueint);
        } else {
            funcCode = value.getBytes();
        }

        header.setFuncCode(funcCode);
    }

    public static void newFuncCode(IMessageHeader header, byte[] funccode) {

        header.setFuncCode(funccode);

        // byte[] funcCode = new byte[header.getFuncCodeLen()];
        //
        // if (header.getStartBitLen() == 2) {
        // funcCode = funccode;
        // header.setFuncCode(funcCode);
        // }else{
        // String ascstr = ByteUtil.toHexString(funccode);
        // header.setFuncCode(ascstr.getBytes());
        // }

    }

    /**
     * 报文上下行标识及长度
     */
    public static void newBodyLength(IMessageHeader header, byte upDown,
                                     int length) {

        // 1000表示下行，0000表示上行
        // byte high4;
        // if (direction.equals("UP")) {
        // high4 = Code.UP;
        // } else {
        // high4 = Code.DOWN;
        // }
        // System.out.println(">>> newBodyLength " + length);
        // 将数据长度与前四位整合
        byte[] lenByte = ByteUtil.ushortToBytes(length);
        byte low4 = (byte) (lenByte[0] & 0x0f);
        byte first = (byte) (upDown | low4);

        header.setBodySize(new byte[]{first, lenByte[1]});

        // HEX编码，value相当于16进制的数
        if (header.getStartBitLen() == 2) {
            header.setBodySize(new byte[]{first, lenByte[1]});
        } else {
            String ascstr = ByteUtil
                    .toHexString(new byte[]{first, lenByte[1]});
            header.setBodySize(ascstr.getBytes());
        }

    }

    /**
     * 报文起始符
     */
    public static void newBodyStartBit(IMessageHeader header,
                                       byte[] _bodyStartBit) {
        // byte[] bodyStartBit = new byte[header.getBodyStartBitLen()];
        // bodyStartBit[0] = Code.STX;
        header.setBodyStartBit(_bodyStartBit);
    }

    /**
     * 报文结束符
     */
    public static void newMessageEOF(IMessage message, String value) {
        byte[] eof = new byte[1];
        eof[0] = Symbol.STX;
        message.setEOF(eof[0]);
    }

    /**
     * 报文校验码
     */
    public static void newMessageCRC(IMessage message, String value) {
        byte[] crc = ByteUtil.HexStringToBinary(value);
        message.setCRC(crc);
    }

    /**
     * 报文的包总数及序列号,需要根据ASC与HEX的不同来构造不同的数据
     */
    public static void newBodyCount(IMessageHeader header, byte[] bodyCount) {
        if (header.getStartBit()[0] == Symbol.SOH_ASC) {
            String ascStr = ByteUtil.byteToHexString(bodyCount);
            header.setBodyCount(ascStr.getBytes());
        } else {
            header.setBodyCount(bodyCount);
        }
    }

    public static void newBodyCount(IMessageHeader header, int amount, int seq) {

        byte[] bodyCount = buildBodyCount(amount, seq);

        newBodyCount(header, bodyCount);

    }

    /**
     * 构造“包总数及序列号”
     *
     * @param count
     * @param serial
     * @return
     */
    public static byte[] buildBodyCount(int count, int serial) {
        byte[] countByte = ByteUtil.ushortToBytes(count);
        byte high = (byte) ((countByte[1] << 4) & 0xF0);

        byte first = (byte) (((countByte[0] & 0x0F) << 4) | ((countByte[1] & 0xF0) >> 4));

        byte[] serialByte = ByteUtil.ushortToBytes(serial);
        byte low = (byte) (serialByte[0] & 0x0f);

        byte middle = (byte) (high | low);

        return new byte[]{first, middle, serialByte[1]};
    }

    public static byte[] toByte(IMessage message, byte updown) {

        IMessageHeader header = message.getHeader();
        IMessageBody body = message.getBody();

        int crclen = 2;
        if (header.getStartBit()[0] == Symbol.SOH_ASC) {
            crclen = 4;
        }

        int size = header.getLength() + body.getLength() + 1 + crclen;
        byte[] content = new byte[size];

        int pos = 0;
        System.arraycopy(header.getStartBit(), 0, content, pos,
                header.getStartBitLen());
        pos = pos + header.getStartBitLen();

        if (Symbol.UP == updown) {
            System.arraycopy(header.getCenterAddr(), 0, content, pos,
                    header.getCenterAddrLen());
            pos = pos + header.getCenterAddrLen();
            System.arraycopy(header.getStationAddr(), 0, content, pos,
                    header.getStationAddrLen());
            pos = pos + header.getStationAddrLen();

        } else {

            System.arraycopy(header.getStationAddr(), 0, content, pos,
                    header.getStationAddrLen());
            pos = pos + header.getStationAddrLen();
            System.arraycopy(header.getCenterAddr(), 0, content, pos,
                    header.getCenterAddrLen());
            pos = pos + header.getCenterAddrLen();
        }
        //---------------------------------
        System.arraycopy(header.getPassword(), 0, content, pos,
                header.getPasswordLen());
        pos = pos + header.getPasswordLen();
        //---------------------------------
        System.arraycopy(header.getFuncCode(), 0, content, pos,
                header.getFuncCodeLen());
        pos = pos + header.getFuncCodeLen();
        //---------------------------------
        System.arraycopy(header.getBodySize(), 0, content, pos,
                header.getBodySizeLen());
        pos = pos + header.getBodySizeLen();
        //---------------------------------
        System.arraycopy(header.getBodyStartBit(), 0, content, pos,
                header.getBodyStartBitLen());
        pos = pos + header.getBodyStartBitLen();
        //---------------------------------
        if (header.getBodyStartBit()[0] == Symbol.SYN) {
            System.arraycopy(header.getBodyCount(), 0, content, pos,
                    header.getBodyCountLen());
            pos = pos + header.getBodyCountLen();
        }
        //---------------------------------
        System.arraycopy(body.getContent(), 0, content, pos,
                body.getLength());
        pos = pos + body.getLength();
        //---------------------------------
        System.arraycopy(new byte[]{message.getEOF()}, 0, content, pos,
                1);
        pos = pos + 1;
        //---------------------------------
        System.arraycopy(message.getCRC(), 0, content, pos,
                message.getCRC().length);

        return content;
    }

    public static String toHexString(IMessageHeader header, byte updown) {
        StringBuffer sb = new StringBuffer(header.getLength());
        sb.append(ByteUtil.toHexString(header.getStartBit()));

        if (Symbol.UP == updown) {
            sb.append(ByteUtil.toHexString(header.getCenterAddr()));
            sb.append(ByteUtil.toHexString(header.getStationAddr()));
        } else {
            sb.append(ByteUtil.toHexString(header.getStationAddr()));
            sb.append(ByteUtil.toHexString(header.getCenterAddr()));
        }
        sb.append(ByteUtil.toHexString(header.getPassword()));
        sb.append(ByteUtil.toHexString(header.getFuncCode()));
        sb.append(ByteUtil.toHexString(header.getBodySize()));

        sb.append(ByteUtil.toHexString(header.getBodyStartBit()));
        if (header.getBodyStartBit()[0] == Symbol.SYN) {
            sb.append(ByteUtil.toHexString(header.getBodyCount()));
        }
        return sb.toString();
    }

    public static String toHexString(IMessage message, byte updown) {
        StringBuffer sb = new StringBuffer();
        sb.append(toHexString(message.getHeader(), updown));
        // sb.append(ByteUtil.toHexString(message.getBody().getContent()));

        if (message.getHeader().getStartBit()[0] == Symbol.SOH_ASC) {

            String hexstr = ByteUtil
                    .toHexString(message.getBody().getContent()).toUpperCase();

            sb.append(ByteUtil.toHexString(hexstr.getBytes()));// 需要将ASC转换为HEX
        } else {
            sb.append(ByteUtil.toHexString(message.getBody().getContent())
                    .toUpperCase());
        }

        sb.append(ByteUtil.toHexString(message.getEOF()));
        sb.append(ByteUtil.toHexString(message.getCRC()));
        return sb.toString().toUpperCase();
    }

    public static void main(String[] args) {
        // HydroBuilder.newStartBut

        AscHeader ascHeader = new AscHeader();
        HydroBuilder.newCenterAddr(ascHeader, "255"); // 1-255,按十六进制数输入
        System.out.println(ByteUtil.toHexString(ascHeader.getCenterAddr()));

        System.out.println("---------------------------------");
        String xxx = "43484C5B305D2D3E6765742061206E657720736D73200D0A";
        String yyy = "112233";

        new String(xxx.getBytes());//

        byte[] b = yyy.getBytes();

        System.out.println(new String(ByteUtil.HexStringToBinary(xxx)));

        // byte lllleeennn = HydroBuilder.buildDataLength(4, 0);
        // System.out.println("lllleeennn = " +
        // ByteUtil.toHexString(lllleeennn));
        //
        // System.out.println("value = " + ByteUtil.toBinaryString((byte)
        // 0x01));
        // for (int i = 0; i < 5; i++) {
        // String value = HydroBuilder.buildDot("000030", i);
        // System.out.println("value = " + value);
        // }
        // String upDown = "DOWN";
        //
        // // 报文正文
        // Up2FBody body = new Up2FBody();
        // // 流水号 ，取值范围01 - 65535
        // body.setSerialId(0);
        //
        // // 发报时间
        // SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmss");
        // body.setSendDate(sdf.format(new Date()));
        // byte[] dest = body.getContent();
        //
        // System.out.println(">> body hex " + Integer.MAX_VALUE);
        //
        // // 报文头
        // HexHeader header = new HexHeader();
        // HydroBuilder.newStartBit(header);
        // HydroBuilder.newCenterAddr(header, "255"); // 1-255,按十六进制数输入
        // HydroBuilder.newStationAddr(header, "12345678");
        // HydroBuilder.newPassword(header, "FFFF");
        // HydroBuilder.newFuncCode(header, "37");
        // HydroBuilder.newBodyLength(header, Symbol.UP, body.getLength());
        // HydroBuilder.newBodyStartBit(header, new byte[] { Symbol.STX });
        //
        // HydroMessage message = new HydroMessage();
        // message.setHeader(header);
        // message.setBody(body);
        // message.setEOF(Symbol.ENQ);
        // // message.setCRC(crc);
        // //
        // // String hexStr = HydroBuilder.toDownHexString(header);
        // // System.out.print(">> hex " + hexStr.toUpperCase());
        // // System.out.print("" + ByteUtil.toHexString(body.getContent()));
        // // System.out.print("" + ByteUtil.toHexString(message.getEOF()));
        // //
        // // // 7E7E0012345678FFFFFF37800802000013022511461705
        // // String crc = CRC16Helper.crc16Check(HydroBuilder
        // // .toDownHexString(header)
        // // + ByteUtil.toHexString(body.getContent())
        // // + ByteUtil.toHexString(message.getEOF()));
        // // System.out.print("  " + crc);
        // //
        // // message.setCRC(ByteUtil.HexStringToBinary(crc));
        //
        // System.out.println("");
        //
        // byte[] b = new byte[1];
        // // 高位表示上下行，1000表示下行，0000表示上行
        // b[0] = Symbol.DOWN;
        // // b[1] = (byte) (((byte) (0 & 0x0f)) << 4);
        //
        // int len = 8;
        // System.out.println(Integer.toHexString(len));
        // System.out.println(Integer.toBinaryString(len));
        // // for (int i = 255; i < 4096; i++) {
        // //
        // // // 将数据长度与前四位整合
        // // byte[] lenByte = ByteUtil.ushortToBytes(i);
        // //
        // // byte high = (byte) (lenByte[0] & 0x0f);
        // // byte aaa = (byte) (b[0] | high);
        // //
        // // System.out.println(">> i = " + i + " byte "
        // // + ByteUtil.byteToHexString(new byte[] { aaa, lenByte[1] }));
        // // }
        // System.out.println(">> hex " + ByteUtil.byteToHexString(b));
    }

}
